package com.campus.delivery.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.common.bean.common.PageUtil;
import com.campus.common.enums.DeliveryProcessEnum;
import com.campus.common.enums.MerchantProcessEnum;
import com.campus.common.enums.OrderStatusEnum;
import com.campus.common.util.ProfitCalculator;
import com.campus.delivery.bean.CompleteOrderBean;
import com.campus.delivery.bean.ConfirmPickupBean;
import com.campus.delivery.bean.GrabOrderBean;
import com.campus.delivery.bean.order.CompletedOrderQueryParam;
import com.campus.delivery.bean.order.OrderListQueryParam;
import com.campus.delivery.entity.Delivery;
import com.campus.delivery.entity.Order;
import com.campus.delivery.entity.OrderGoods;
import com.campus.delivery.entity.User;
import com.campus.delivery.mapper.DeliveryMapper;
import com.campus.delivery.mapper.OrderGoodsMapper;
import com.campus.delivery.mapper.OrderMapper;
import com.campus.delivery.vo.OrderVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author ZhaoYuJie
 * @since 2025-05-12
 */
@Service
@Slf4j
public class OrderService extends ServiceImpl<OrderMapper, Order> {
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private DeliveryMapper deliveryMapper;
    @Autowired
    private WebSocketService webSocketService;
    @Autowired
    private OrderCompleteMessageProducer orderCompleteMessageProducer;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisService redisService;
    
    @Value("${campus.profit.delivery-commission-rate:0.2}")
    private BigDecimal deliveryCommissionRate;
    
    @Value("${campus.profit.service-fee-rate:0.1}")
    private BigDecimal serviceFeeRate;

    public OrderService(OrderGoodsMapper orderGoodsMapper) {
        this.orderGoodsMapper = orderGoodsMapper;
    }

    public PageInfo<OrderVo> getOrderListPage(OrderListQueryParam param) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getDeliveryProcess, param.getDeliveryProcess());
        if (param.getDeliveryId() != null) {
            wrapper.eq(Order::getDeliveryId, param.getDeliveryId());
            //根据商家进度和创建时间倒序排序
            wrapper.orderByDesc(Order::getMerchantProcess).orderByDesc(Order::getCreateTime);
        }else{
            //根据商家进度倒序排序，创建时间升序排序
            wrapper.orderByDesc(Order::getMerchantProcess).orderByAsc(Order::getCreateTime);
        }

        PageInfo<Order> pageInfo = PageHelper.startPage(param.getPageNo(), param.getPageSize())
                .doSelectPageInfo(() -> list(wrapper));
        
        List<OrderVo> orderVOList = convertToOrderVoList(pageInfo.getList());

        return PageUtil.convertPageInfo(pageInfo, orderVOList);
    }
    private List<OrderVo> convertToOrderVoList(List<Order> orders) {
        List<OrderVo> voList = new ArrayList<>();
        for (Order order : orders) {
            OrderVo vo = new OrderVo();
            BeanUtil.copyProperties(order, vo);
            // 查询订单商品
            List<OrderGoods> goodsList = orderGoodsMapper.selectList(
                    new LambdaQueryWrapper<OrderGoods>().eq(OrderGoods::getOrderId, order.getId())
            );
            List<OrderVo.OrderGoodsVo> goodsVOList = new ArrayList<>();
            for (OrderGoods goods : goodsList) {
                OrderVo.OrderGoodsVo goodsVO = new OrderVo.OrderGoodsVo();
                BeanUtil.copyProperties(goods, goodsVO);
                goodsVOList.add(goodsVO);
            }
            vo.setGoods(goodsVOList);
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 配送员抢单
     * @param bean 抢单参数
     */
    public void grabOrder(GrabOrderBean bean) {
        // 生成锁的key和value
        String lockKey = redisService.getOrderGrabLockKey(bean.getOrderId());
        String lockValue = "delivery:" + bean.getDeliveryId() + ":" + System.currentTimeMillis();
        
        // 尝试获取分布式锁，设置30秒过期时间
        boolean lockAcquired = redisService.tryLock(lockKey, lockValue, 30L);
        
        if (!lockAcquired) {
            throw new RuntimeException("该订单正在被其他配送员抢单，请稍后重试");
        }
        
        try {
            // 重新查询订单状态，确保数据一致性
            Order order = getById(bean.getOrderId());
            if (order == null) {
                throw new RuntimeException("订单不存在");
            }
            
            if (order.getDeliveryProcess() != 0) {
                throw new RuntimeException("订单状态不正确或已被抢，无法抢单");
            }
            
            // 检查配送员是否存在
            Delivery delivery = deliveryMapper.selectById(bean.getDeliveryId());
            if (delivery == null) {
                throw new RuntimeException("配送员不存在");
            }
            
            // 更新订单状态
            order.setDeliveryProcess(DeliveryProcessEnum.PENDING_PICKUP.getValue()); // 更新为待取餐
            order.setDeliveryProcessText(DeliveryProcessEnum.PENDING_PICKUP.getText());
            order.setDeliveryId(bean.getDeliveryId());
            order.setDeliveryPhone(delivery.getPhone());
            
            boolean updateSuccess = updateById(order);
            if (!updateSuccess) {
                throw new RuntimeException("抢单失败，请重试");
            }
            
            log.info("配送员{}成功抢到订单{}", bean.getDeliveryId(), bean.getOrderId());
            
            // 广播订单状态变更给所有在线配送员
            webSocketService.broadcastOrderStatusChange(
                bean.getOrderId(), 
                DeliveryProcessEnum.PENDING_PICKUP.getValue(), 
                bean.getDeliveryId()
            );
            
            // 如果订单的商家进度为已出餐，则推送websocket消息通知配送员取餐
            if (order.getMerchantProcess() == MerchantProcessEnum.MEAL_READY.getValue()) {
                String notificationContent = "订单" + bean.getOrderId() + "已出餐，请及时取餐配送！";
                webSocketService.sendMealReadyNotification(bean.getDeliveryId(), notificationContent);
            }
            
        } catch (Exception e) {
            log.error("抢单过程中发生异常，订单ID: {}, 配送员ID: {}", bean.getOrderId(), bean.getDeliveryId(), e);
            throw e;
        } finally {
            // 无论成功还是失败，都要释放锁
            boolean lockReleased = redisService.releaseLock(lockKey, lockValue);
            if (!lockReleased) {
                log.warn("释放抢单锁失败，订单ID: {}, 配送员ID: {}", bean.getOrderId(), bean.getDeliveryId());
            }
        }
    }

    /**
     * 配送员确认取货
     * @param param 确认取货参数
     */
    public void confirmPickup(ConfirmPickupBean param) {
        Order order = getById(param.getOrderId());
        if (order != null && order.getDeliveryProcess() == DeliveryProcessEnum.PENDING_PICKUP.getValue()) { // 确保订单处于待取餐状态
            order.setDeliveryProcess(DeliveryProcessEnum.DELIVERING.getValue()); // 更新为配送中
            order.setDeliveryProcessText(DeliveryProcessEnum.DELIVERING.getText());
            updateById(order);
        } else {
             throw new RuntimeException("订单状态不正确，无法确认取货");
        }
    }

    /**
     * 配送员确认送达
     * @param param 确认送达参数
     */
    public void completeOrder(CompleteOrderBean param) {
         Order order = getById(param.getOrderId());
        if (order != null && order.getDeliveryProcess() == DeliveryProcessEnum.DELIVERING.getValue()) { // 确保订单处于配送中状态
            order.setDeliveryProcess(DeliveryProcessEnum.DELIVERED.getValue()); // 更新为已送达
            order.setDeliveryProcessText(DeliveryProcessEnum.DELIVERED.getText());
            order.setDeliveryTime(LocalDateTime.now());
            //订单状态设置为已完成
            order.setStatus(OrderStatusEnum.COMPLETED.getValue());
            order.setStatusText(OrderStatusEnum.COMPLETED.getText());
            order.setFinishTime(LocalDateTime.now());
            
            // 计算各方收益
            calculateAndSetProfit(order);
            
            // 发送订单完成通知给顾客
            try {
                // 获取用户信息
                User user = userService.getById(order.getUserId());
                if (user != null && user.getOpenid() != null) {
                    // 获取订单商品信息用于构建货品名称
                    List<OrderGoods> goodsList = orderGoodsMapper.selectList(
                        new LambdaQueryWrapper<OrderGoods>().eq(OrderGoods::getOrderId, order.getId())
                    );
                    String goodsName = "";
                    if (!goodsList.isEmpty()) {
                        if (goodsList.size() == 1) {
                            goodsName = goodsList.get(0).getName();
                        } else {
                            goodsName = goodsList.get(0).getName() + "等" + goodsList.size() + "件商品";
                        }
                    }
                    
                    // 通过Kafka发送订单完成消息到顾客端
                    orderCompleteMessageProducer.sendOrderCompleteMessage(
                        user.getOpenid(),
                        order.getId(),
                        goodsName,
                        order.getActualPay(),
                        LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
                        "配送员确认商品已送达"
                    );
                    log.info("订单完成通知已发送，订单号: {}", param.getOrderId());
                }
            } catch (Exception e) {
                // 订单完成成功，但通知发送失败不影响业务流程
                log.error("发送订单完成通知失败，订单号: {}", param.getOrderId(), e);
            }
            
            updateById(order);
        } else {
             throw new RuntimeException("订单状态不正确，无法确认送达");
        }
    }
    
    /**
     * 根据订单ID获取订单详情
     * @param orderId 订单ID
     * @return 订单详情VO
     */
    public OrderVo getOrderDetail(String orderId) {
        // 查询订单主表
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        // 复制主表属性到VO
        OrderVo orderVo = new OrderVo();
        BeanUtil.copyProperties(order, orderVo);
        // 查询订单商品列表
        List<OrderGoods> goodsList = orderGoodsMapper.selectList(new LambdaQueryWrapper<OrderGoods>().eq(OrderGoods::getOrderId, orderId));
        List<OrderVo.OrderGoodsVo> goodsVoList = new ArrayList<>();
        for (OrderGoods goods : goodsList) {
            OrderVo.OrderGoodsVo goodsVo = new OrderVo.OrderGoodsVo();
            BeanUtil.copyProperties(goods, goodsVo);
            goodsVoList.add(goodsVo);
        }
        orderVo.setGoods(goodsVoList);
        return orderVo;
    }

    /**
     * 获取已完成的订单列表
     * @param param 查询参数
     * @return 已完成订单分页列表
     */
    public PageInfo<OrderVo> getCompletedOrdersPage(CompletedOrderQueryParam param) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        // 查询指定配送员的订单
        wrapper.eq(Order::getDeliveryId, param.getDeliveryId());
        // 查询已送达的订单
        wrapper.eq(Order::getDeliveryProcess, DeliveryProcessEnum.DELIVERED.getValue());
        // 按完成时间倒序排序
        wrapper.orderByDesc(Order::getFinishTime);
        
        PageInfo<Order> pageInfo = PageHelper.startPage(param.getPageNo(), param.getPageSize())
                .doSelectPageInfo(() -> list(wrapper));
        
        List<OrderVo> orderVOList = convertToOrderVoList(pageInfo.getList());
        
        return PageUtil.convertPageInfo(pageInfo, orderVOList);
    }
    
    /**
     * 计算并设置订单各方收益
     * @param order 订单对象
     */
    private void calculateAndSetProfit(Order order) {
        try {
            // 获取订单金额信息
            BigDecimal actualPay = order.getActualPay();
            BigDecimal deliveryFee = order.getDeliveryFee() != null ? order.getDeliveryFee() : BigDecimal.ZERO;
            
            // 计算各方收益
            ProfitCalculator.ProfitResult profitResult = ProfitCalculator.calculateProfit(
                actualPay, deliveryFee, deliveryCommissionRate, serviceFeeRate);
            
            // 设置收益字段
            order.setDeliveryProfit(profitResult.getDeliveryProfit());
            order.setPlatformProfit(profitResult.getPlatformProfit());
            order.setMerchantProfit(profitResult.getMerchantProfit());
            
            log.info("订单{}收益计算完成 - 配送员收益:{}, 平台收益:{}, 商户收益:{}", 
                order.getId(), 
                profitResult.getDeliveryProfit(), 
                profitResult.getPlatformProfit(), 
                profitResult.getMerchantProfit());
                
        } catch (Exception e) {
            log.error("订单{}收益计算失败", order.getId(), e);
            // 收益计算失败不影响订单完成流程
        }
    }

}
